'''
 * CaRComp Execution Environment
 * 
 * Copyright (C) 2011 Taylor L. Riche
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
'''

from carcomp.framework import application, component
from carcomp.framework.net_io import *
from carcomp.framework.quorum import gen_quorum
from carcomp.directory import localhost
from carcomp.apps.ft.messages import agree_msgs

class OutTrans(component.Implementation):
    
    def trans_msg(self, msg):
        self.send_out('out', (localhost.AGREE0_NAME,msg))
        
    def check_for_help(self, msg):
        print('Received: ' + str(msg))
        message = agree_msgs.Message(msg)
        if message.cmd == agree_msgs.FTCMD_FETCH:
            self.send_out('out', (localhost.AGREE0_NAME, msg))
        else:
            self.send_out('take_q', msg)

class Quorum(application.Application):
    '''
    classdocs
    '''

    def __init__(self):
        '''
        Constructor
        '''
        application.Application.__init__(self)
        
    def setup(self):
        
        quorum_comp = gen_quorum.GenericQuorum('quorum_comp', localhost.local_directory.server_q_thresh)
        self.create_component(quorum_comp, [('in', 'process_msg'), ('q_found', '__OUT__')])
        
        trans_comp = OutTrans('trans_comp')
        self.create_component(trans_comp, [('in', 'trans_msg'), ('new_msg', 'check_for_help'), 
                                           ('out', '__OUT__'), ('take_q', '__OUT__')])
        
        nr = net_reader.NetReaderComponent(self._node_name, localhost.local_directory)
        nw = net_writer.NetWriterComponent('netout', self._node_name, localhost.local_directory)
        
        self.add_components([nr, nw])
        
        #nr_to_quorum = self.create_connection((self._node_name, 'out'), ('quorum_comp', 'in'))
        nr_to_trans = self.create_connection((self._node_name, 'out'), ('trans_comp','new_msg'))
        trans_to_quorum = self.create_connection(('trans_comp', 'take_q'), ('quorum_comp', 'in'))
        quorum_to_trans = self.create_connection(('quorum_comp', 'q_found'),('trans_comp','in'))
        trans_to_nw = self.create_connection(('trans_comp', 'out'), ('netout', 'in'))

        nr_thread = application.CompThread(nr, [nr_to_trans], True)
        nw_thread = application.CompThread(nw, [trans_to_nw])
        quorum_thread = application.CompThread(quorum_comp, [trans_to_quorum, quorum_to_trans])
        trans_thread = application.CompThread(trans_comp, [trans_to_quorum, quorum_to_trans, trans_to_nw, nr_to_trans])

        self.add_threads([nr_thread, nw_thread, quorum_thread, trans_thread])
        
if __name__ == '__main__':
    quorum = Quorum()
    quorum.parse_opts()
    quorum.setup()
    quorum.execute()
